package cn.gaozhong.ymcc.service.impl;

import cn.gaozhong.ymcc.domain.Course;
import cn.gaozhong.ymcc.domain.CourseMarket;
import cn.gaozhong.ymcc.domain.CourseOrder;
import cn.gaozhong.ymcc.domain.CourseOrderItem;
import cn.gaozhong.ymcc.dto.CourseOrderCreateParamsDto;
import cn.gaozhong.ymcc.dto.PayDto;
import cn.gaozhong.ymcc.exception.GlobalException;
import cn.gaozhong.ymcc.feign.CourseUserLearnFeignClient;
import cn.gaozhong.ymcc.mapper.CourseOrderMapper;
import cn.gaozhong.ymcc.result.JSONResult;
import cn.gaozhong.ymcc.service.ICourseOrderItemService;
import cn.gaozhong.ymcc.service.ICourseOrderService;
import cn.gaozhong.ymcc.util.AssertUtil;
import cn.gaozhong.ymcc.util.CodeGenerateUtils;
import cn.gaozhong.ymcc.vo.CourseItemVo;
import cn.gaozhong.ymcc.vo.CourseOrderInfoVc;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.apache.rocketmq.client.producer.LocalTransactionState;
import org.apache.rocketmq.client.producer.SendStatus;
import org.apache.rocketmq.client.producer.TransactionSendResult;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.HashMap;
import java.util.List;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author GZ.gaozhong
 * @since 2022-07-29
 */
@Service
@Slf4j
public class CourseOrderServiceImpl extends ServiceImpl<CourseOrderMapper, CourseOrder> implements ICourseOrderService {

    @Autowired
    private RedisTemplate<Object,Object> redisTemplatel;

    @Autowired
    private CourseUserLearnFeignClient courseOrderFeignClient;
    @Autowired
    private ICourseOrderItemService courseOrderItemService;

    @Autowired
    private RocketMQTemplate rocketMQTemplate;

    @Override
    public String placeOrder(CourseOrderCreateParamsDto dto) {
        String id = StringUtils.join(dto.getCourseIds(), ",");
        Long loginId = 1L;
        String key = id+":"+loginId;
        Object token = redisTemplatel.opsForValue().get(key);
        AssertUtil.isNotNull(token,"token失效请重新获取");
        AssertUtil.isEquals(dto.getToken(),token.toString(),"token不一致请重新下单");
        JSONResult jsonResult = courseOrderFeignClient.orderInfo(id);
        AssertUtil.isTrue(jsonResult.isSuccess(),"信息错误，下单失败");
        AssertUtil.isNotNull(jsonResult.getData(),"服务不可达");
        String s = JSON.toJSONString(jsonResult.getData());
        CourseItemVo orderVo = JSONObject.parseObject(s, CourseItemVo.class);
        List<CourseOrderInfoVc> courseInfos = orderVo.getCourseInfos();
        AssertUtil.isNotNull(courseInfos,"课程信息有误，下单失败");
        Date date = new Date();
        CourseOrder courseOrder = new CourseOrder();
        courseOrder.setCreateTime(date);
        courseOrder.setOrderNo(CodeGenerateUtils.generateOrderSn(loginId));
        courseOrder.setStatusOrder(1);
        courseOrder.setUserId(loginId);
        courseOrder.setVersion(0);
        courseOrder.setPayType(1);
//        insert(courseOrder);
        StringBuilder sb = new StringBuilder();
        sb.append("课程【");
        courseInfos.forEach(courseOrderInfoVc->{
            Course course = courseOrderInfoVc.getCourse();
            CourseMarket courseMarket = courseOrderInfoVc.getCourseMarket();
            CourseOrderItem courseOrderItem = new CourseOrderItem();
//            courseOrderItem.setOrderId(courseOrder.getId());
            courseOrderItem.setAmount(courseMarket.getPrice());
            courseOrderItem.setCount(1);
            courseOrder.setTotalCount(courseOrder.getTotalCount() + 1);
            courseOrder.setTotalAmount(courseOrder.getTotalAmount().add(courseOrderItem.getAmount()));
            sb.append(course.getName()).append(",");
            courseOrderItem.setCourseId(course.getId());
            courseOrderItem.setCourseName(course.getName());
            courseOrderItem.setCoursePic(course.getPic());
            courseOrderItem.setVersion(courseOrder.getVersion());
            courseOrderItem.setOrderNo(courseOrder.getOrderNo());
//            courseOrderItemService.insert(courseOrderItem);
        });
        sb.append("】订单");
        //修改主订单
        courseOrder.setTitle(sb.toString());
//        updateById(courseOrder);

        //删除防重复token
        redisTemplatel.delete(key);
        HashMap<Object, Object> extParam = new HashMap<>();
        extParam.put("userId",loginId);
        extParam.put("courseId",id);
        PayDto payDto = new PayDto(
                courseOrder.getTotalAmount(),
                courseOrder.getPayType(),
                null,
                courseOrder.getOrderNo(),
                courseOrder.getUserId(),
                JSON.toJSONString(extParam),
                courseOrder.getTitle()
        );
        log.info("发送事务消息");

        //构建消息体
        Message<String> message = MessageBuilder.withPayload(JSON.toJSONString(payDto)).build();
        TransactionSendResult transactionSendResult = rocketMQTemplate.sendMessageInTransaction(
                "service-order-producer",
                "course-order-topic:course-order-tag",
                message,
                courseOrder
        );
        log.info("检查事务消息状态");
        LocalTransactionState localTransactionState = transactionSendResult.getLocalTransactionState();
        SendStatus sendStatus = transactionSendResult.getSendStatus();
        if(localTransactionState != LocalTransactionState.COMMIT_MESSAGE || sendStatus != SendStatus.SEND_OK ){
            log.info("校验事务消息状态异常");
            throw new GlobalException("下单失败！！");
        }
        //发布事务消息
        //删除防重复token
        redisTemplatel.delete(key);
        return courseOrder.getOrderNo();
    }
    @Override
    public void saveOrderAndItems(CourseOrder courseOrder) {
        CourseOrder orderTmp = selectOrderByOrderNo(courseOrder.getOrderNo());
        AssertUtil.isNull(orderTmp,"订单存在，下单失败");
        //保存订单
        insert(courseOrder);
        courseOrder.getItems().forEach(courseOrderItem->{
            courseOrderItem.setOrderId(courseOrder.getId());
            courseOrderItemService.insert(courseOrderItem);
        });
    }

    /**
     * 根据订单号查询订单
     * @param orderNo
     * @return
     */
    @Override
    public CourseOrder selectOrderByOrderNo(String orderNo) {
        Wrapper<CourseOrder> wrapper = new EntityWrapper<>();
        wrapper.eq("order_no",orderNo);
        return selectOne(wrapper);
    }
    @Override
    public void payOrder(CourseOrder courseOrder) {
        courseOrder.setStatusOrder(CourseOrder.STATE_PAY_SUCCESS);
        courseOrder.setUpdateTime(new Date());
        updateById(courseOrder);
    }

    @Override
    public void cancelOrder(String orderNo) {
        CourseOrder courseOrder = selectOrderByOrderNo(orderNo);
        AssertUtil.isNotNull(courseOrder,"订单不存在");
        if(courseOrder.getStatusOrder().intValue() != CourseOrder.STATE_PAY_SUCCESS.intValue()){
            courseOrder.setStatusOrder(CourseOrder.STATE_CANCEL);
            updateById(courseOrder);
        }
    }
}
